///
/// Wave file operations including read and write
/// 
/// @Author Jun Xu
/// @Date 2007-11-12
/// @Version 1.0
/// 
#ifndef _CST_COMMON_WAVEFILE_H_
#define _CST_COMMON_WAVEFILE_H_

#include "basictypes.h"

#pragma pack(1)
/// OLD general waveform format structure (information common to all formats)
//struct CSTWAVEFORMAT
//{
//    u_int16 wFormatTag;        /* format type */
//    u_int16 nChannels;         /* number of channels (i.e. mono, stereo, etc.) */
//    u_int32 nSamplesPerSec;    /* sample rate */
//    u_int32 nAvgBytesPerSec;   /* for buffer estimation */
//    u_int16 nBlockAlign;       /* block size of data */
//    u_int16 wBitsPerSample;    /* for alignment, add by Dezhi HUANG */
//};
//
//struct WAVEFILEHEADSTRUCT
//{
//    char    FileHead1[4];
//    int     FileLength;
//    char    FileHead2[8];
//    int     Reserve;
//    CSTWAVEFORMAT  PcmWaveFormat;
//    char    DataPoint[4];
//    int     nWaveLength;
//};

struct TRIFFChunk 
{
    void    reset();
    char    id[4];
    u_int32 size;
    char    type[4];
};

struct TFormatChunk
{
    void    reset(u_int32 sr = 16000, u_int16 bitn = 16, u_int16 chnl = 1, u_int16 rsv = 0);

    char    id[4];
    u_int32 size;               ///< 16 or 18, when size is 18, the file contains the 2 bytes of reserve
    u_int16 tag;
    u_int16 channel;
    u_int32 sample_rate;
    u_int32 avg_sample_rate;
    u_int16 block_align;
    u_int16 bit_num;
    u_int16 reserve;
};

struct TFactChunk
{
    void    reset();

    char    id[4];
    u_int32 size;
};

struct TDataChunk
{
    void    reset();

    char    id[4];
    u_int32 size;
};

struct TWAVEHEADER 
{
    TRIFFChunk      riff;
    TFormatChunk    format;
    //TFactChunk      fact;
    TDataChunk      data;
};

#pragma pack()

class CWaveFile 
{
public:
    CWaveFile(){}
    ~CWaveFile(){}
public:
    /// 
    /// Read from file with provided buffer
    /// Return actual read length if OK
    /// Return -1 if error
    /// Return the actual file length without reading if buffer is not enough
    /// 
    static int readWaveWithBuffer(const char *strFile, void *pWave, u_int32 nLength, u_int32 *nSampleRate = 0, u_int32 *nBitNum = 0, u_int32 *nChannel = 0);
    
    /// Read wave file
    static bool readWave(const char *strFile, void *&pWave, u_int32 &nLength, u_int32 *nSampleRate = 0, u_int16 *nBitNum = 0, u_int16 *nChannel = 0);
    static bool getWaveLength(const char *strFile, u_int32 &nLength);
    static bool writeWave(const char *strFile, const void *pWave, u_int32 nLength, u_int32 nSampleRate = 16000, u_int16 nBitNum = 16, u_int16 nChannel = 1, bool bAppend = false);
    static bool testWaveExsits(const char *filename);
    static void freeWaveData(void *waveData);
    static void resetWaveHead(TWAVEHEADER *pWaveFileHead, u_int32 nSampleRate, u_int16 nBitNum = 16, u_int16 nChannel = 1, u_int16 nReserve = 0);
    
};

#endif
